/**************************************************************************//**
 * @item     CosyOS Kernel
 * @file     os_taskmge.c
 * @brief    SysTick_Handler and PendSV_Handler2
 * @author   迟凯峰
 * @version  V3.3.5
 * @date     2023.09.12
 ******************************************************************************/

#include "os_link.h"

#if SYSCFG_DEBUGGING == __ENABLED__
static u32 usedtime[2]; // 用于统计各任务的CPU利用率
#endif

void SysTick_Handler(void) __STK_ATTRIBUTE__
{
	tTID _SYS_REG_ i;
	/* 系统滴答时间统计 */
	#if SYSCFG_STKTIMECOUNT == __ENABLED__
	static tSysTick tick_temp;
	if(vTaskmgrBinary)
	{
		tick_temp = mSysTick_Counter;
	}
	#endif
	/* 软件RTC */
	#if SYSCFG_SOFTRTC == __ENABLED__
	{
		static
		#if SYSCFG_STKCYCLE > 1000000UL / 65536
		u16
		#else
		u32
		#endif
		_SYS_MEM_ counter = 0;
		static u8 _SYS_MEM_ rtc[7] = sInitRealTime;
		static tsVarNode var_node = {vRealTime, rtc};
		if(counter < 1000000UL / SYSCFG_STKCYCLE - 1) counter++;
		else
		{
			counter = 0;
			vEvery.second = true;
			if(rtc[5] < 59) rtc[5]++;
			else
			{
				rtc[5] = 0;
				vEvery.minute = true;
				if(rtc[4] < 59) rtc[4]++;
				else
				{
					rtc[4] = 0;
					vEvery.hour = true;
					if(rtc[3] < 23) rtc[3]++;
					else
					{
						rtc[3] = 0;
						vEvery.day = true;
						if(rtc[6] < 7) rtc[6]++;
						else rtc[6] = 1;
						if(rtc[2] < (rtc[1] == 2 ? vMonth2Date : cMonthDate[rtc[1]])) rtc[2]++;
						else
						{
							rtc[2] = 1;
							vEvery.month = true;
							if(rtc[1] < 12) rtc[1]++;
							else
							{
								rtc[1] = 1;
								vEvery.year = true;
								if(rtc[0] < 99) rtc[0]++;
								else rtc[0] = 0;
							}
						}
					}
				}
			}
		}
		sWRITE_VAR_WRITE(&var_node);
		*(u32 *)(vRealTime + 0) = *(u32 *)(rtc + 0);
		*(u16 *)(vRealTime + 4) = *(u16 *)(rtc + 4);
		*(u8  *)(vRealTime + 6) = *(u8  *)(rtc + 6);
		sWRITE_VAR_WRITE(NULL);
	}
	#endif
	/* 调用滴答钩子 */
	#if SYSCFG_TICKHOOK == __ENABLED__
	tick_hook();
	#endif
	/* 定时中断 */
	#if OS_TIMINTTOTAL
	i = OS_TIMINTTOTAL;
	while(i--)
	{
		if(vTIMINT_STMR[i] && vTIMINT_STMR[i] < ~0)
		{
			vTIMINT_STMR[i]--; // 定时中断定时器计数
			if(!vTIMINT_STMR[i])
			{
				if(vTIMINT_TYPE[i])
				{
					sResumeTask_TimInt(i); // 恢复定时中断任务
				}
				else
				{
					(*vTIMINT_THDL[i]->HOOK)(); // 调用定时中断钩子
				}
				if(vTIMINT_ARLD[i])
				{
					vTIMINT_STMR[i] = vTIMINT_BUFF[i]; // 定时中断定时器重装载
				}
			}
		}
	}
	#endif
	/* 定时查询 */
	#if OS_TIMQRYTOTAL
	i = OS_TIMQRYTOTAL;
	while(i--)
	{
		if(vTIMQRY_STMR[i] && vTIMQRY_STMR[i] < ~0)
		{
			vTIMQRY_STMR[i]--; // 定时查询定时器计数
		}
		if(!vTIMQRY_STMR[i])
		{
			if((*vTIMQRY_THDL[i]->EVENT)()) // 调用定时查询事件钩子
			{
				if(vTIMQRY_TYPE[i])
				{
					sResumeTask_TimQry(i); // 恢复定时查询任务
				}
				else
				{
					(*vTIMQRY_THDL[i]->HOOK)(); // 调用定时查询钩子
				}
				if(vTIMQRY_ARLD[i])
				{
					vTIMQRY_STMR[i] = vTIMQRY_BUFF[i]; // 定时查询定时器重装载
				}
				else
				{
					vTIMQRY_STMR[i] = ~0; // 终止定时查询
				}
			}
		}
	}
	#endif
	/* 延时定时器 */
	i = OS_TASKTOTAL;
	do{
		if(vDELAY_STMR[i] && vDELAY_STMR[i] < ~0)
		{
			vDELAY_STMR[i]--; // 延时定时器计数
		}
	}while(--i);
	/* 时间片滴答计数 */
	vTickCounter++;
	/* 安全运行时 */
	#if SYSCFG_SAFERUNTIME == __ENABLED__
	if(vTASKING != NULL && vTASKING->TPL && vTASKING->saferuntime)
	{
		vTASKING->counter++;
		if(vTASKING->counter > 1UL * vTASKING->saferuntime * OS_TIMESHARING)
		{
			vTASKING->state = __OVERTIME__;
			vOVERTIME[vTASKING->TID] = true;
			#if SYSCFG_DEBUGGING == __ENABLED__
			vAlarm.overtime_saferuntime = true;
			#endif
		}
	}
	#endif
	/* 任务管理器相关 */
	#if SYSCFG_DEBUGGING == __ENABLED__
	if(vTaskmgrBinary)
	{
		usedtime[0]++;
		#if SYSCFG_STKTIMECOUNT == __ENABLED__
		mSTK_Counting;
		#endif
	}
	#endif
	/* 触发任务调度（定时调度）*/
	if(!vRET_f)
	{
		vScheduling_f = true;
		mPSV_Trigger;
	}
}

/* 任务节点 */
#define	node_head       task_node[0]    // 头节点
#define	node_midd       task_node[1]    // 中间节点
#define	node_tail       task_node[2]    // 尾节点
#define	node_curr       node_buff[0]    // 当前节点
#define	node_news       node_buff[1]    // 新加节点
#define	node_temp       node_buff[2]    // 临时节点
#define	node_last       node_curr->last // 上一节点（当前节点的上一节点）
#define	node_next       node_curr->next // 下一节点（当前节点的下一节点）

/* 初始化任务队列（CosyOS的任务队列为双向循环链表）*/
#define	init_taskqueue  node_head = node_midd = node_tail = node_news->last = node_news->next = node_news
#define	init_node_head  node_curr = node_head // 初始化头节点（头节点为当前节点）
#define	init_node_midd  node_curr = node_midd // 初始化中间节点（中间节点为当前节点）
#define	move_forward    node_curr = node_last // 节点前移（当前节点向前移动）
#define	move_backward   node_curr = node_next // 节点后移（当前节点向后移动）

/* 移除节点（从任务队列中移除当前节点）*/
#define	node_remove	\
do{	\
	node_last->next = node_next;	\
	node_next->last = node_last;	\
	if(node_curr == node_head)	\
	{	\
		node_head = node_next;	\
	}	\
	task_queue_len--;	\
}while(false)

/* 插入方向 */
#define forward   0x01 // 向前
#define voidward  0x00 // 空
#define backward  0xFF // 向后

/* 前插（新加节点插入当前节点之前）*/
#define	insert_forward	\
do{	\
	node_news->next = node_curr;	\
	node_news->last = node_last;	\
	node_last->next = node_news;	\
	node_last = node_news;	\
	if(node_curr == node_head)	\
	{	\
		node_head = node_news;	\
	}	\
	switch(insert_direction)	\
	{	\
		case forward:  insert_direction = voidward; node_midd = node_midd->last; break;	\
		case voidward: insert_direction = forward;  break;	\
		case backward: insert_direction = voidward; break;	\
	}	\
}while(false)

/* 后插（新加节点插入当前节点之后）*/
#define	insert_backward	\
do{	\
	node_news->last = node_curr;	\
	node_news->next = node_next;	\
	node_next->last = node_news;	\
	node_next = node_news;	\
	if(node_curr == node_tail)	\
	{	\
		node_tail = node_news;	\
	}	\
	switch(insert_direction)	\
	{	\
		case forward:  insert_direction = voidward; break;	\
		case voidward: insert_direction = backward; break;	\
		case backward: insert_direction = voidward; node_midd = node_midd->next; break;	\
	}	\
}while(false)

#define task_state_over	\
do{	\
	if(!rotate_f)	\
	{	\
		node_news = node_curr;	\
		/* 首次任务调度 || 新任务与当前任务优先级不同 -> 任务调度 */	\
		if(vTASKING == NULL || node_news->TPL != vTASKING->TPL) goto __TASK_SCHEDULING;	\
		/* 将依次查询当前任务优先级组的所有任务（稍后将有可能进行时间片轮转调度）*/	\
		rotate_f = true;	\
	}	\
}while(false)

#if SYSCFG_MCUCORE == 80251
#pragma functions(static)
#endif
void PendSV_Handler2(void) __PSV_ATTRIBUTE__
{
/* 中断异步服务的执行 */
mISV;
/* 任务调度 */
if(vScheduling_f)
{
	static u8            _SYS_MEM_ insert_direction = 0;
	static tTaskQueueLen _SYS_MEM_ task_queue_len = 0;
	static tspTaskNode   _SYS_MEM_ task_node[3] = {NULL};
				 tspTaskNode   _SYS_REG_ node_buff[3];
	#if SYSCFG_DEBUGGING == __ENABLED__
				 tSysTick      _SYS_REG_ counter;
	#endif
	tBIT push_f = false;
	tBIT rotate_f = false;
	/* 调度初始化 */
	mScheduler_INIT;
	/* 启动任务 */
	if(vACTBUF != NULL)
	{
		if(task_queue_len < __TASKQUEUEMAXLEN__)
		{
			#if SYSCFG_TASKCREATEMODE == __STATIC__
			node_news = vACTBUF;
			if(node_news->stacksize < __BASICSTACKSIZE__)
			{
				#if SYSCFG_DEBUGGING == __ENABLED__
				vFault.fail_startuptask = true;
				vFault.overflow_taskstack = true;
				#endif
				vACTRET = ECODE_OVERFLOW_TASKSTACK;
				goto __ACTEND;
			}
			{
				mTaskStack_INIT;
				if(node_news->TPL0 <= (u8)(SYSCFG_TASKPRIORITY - 1))
				{
					node_news->TPL = node_news->TPL0;
				}
				else
				{
					node_news->TPL = SYSCFG_TASKPRIORITY - 2;
					#if SYSCFG_DEBUGGING == __ENABLED__
					vAlarm.overflow_taskpriority = true;
					#endif
				}
				node_news->blocktype = 0;
				node_news->ptr = NULL;
				#if SYSCFG_DEBUGGING == __ENABLED__
				node_news->usedtime[0] = 0;
				node_news->usedtime[1] = 0;
				node_news->stacklen_max = __BASICSTACKSIZE__;
				#endif
				node_news->counter = 0;
				vDELAY_STMR[node_news->TID] = 0;
			}
			#elif SYSCFG_TASKCREATEMODE == __BALANCE__
			node_news = vACTBUF;
			if(node_news->stacksize < __BASICSTACKSIZE__)
			{
				node_news->stacksize = __BASICSTACKSIZE__;
				#if SYSCFG_DEBUGGING == __ENABLED__
				node_news->realloc = true;
				#endif
			}
			#if SYSCFG_DEBUGGING == __ENABLED__
			else
			{
				node_news->realloc = false;
			}
			#endif
			node_news->BSP = NULL;
			node_news->BSP = (u8 *)__malloc(node_news->stacksize);
			if(node_news->BSP != NULL)
			{
				mTaskStack_INIT;
				if(node_news->TPL0 <= (u8)(SYSCFG_TASKPRIORITY - 1))
				{
					node_news->TPL = node_news->TPL0;
				}
				else
				{
					node_news->TPL = SYSCFG_TASKPRIORITY - 2;
					#if SYSCFG_DEBUGGING == __ENABLED__
					vAlarm.overflow_taskpriority = true;
					#endif
				}
				node_news->blocktype = 0;
				node_news->ptr = NULL;
				#if SYSCFG_DEBUGGING == __ENABLED__
				node_news->usedtime[0] = 0;
				node_news->usedtime[1] = 0;
				node_news->stacklen_max = __BASICSTACKSIZE__;
				#endif
				node_news->counter = 0;
				vDELAY_STMR[node_news->TID] = 0;
			}
			else
			{
				#if SYSCFG_DEBUGGING == __ENABLED__
				vFault.fail_startuptask = true;
				vFault.mallocfail_taskstack = true;
				#endif
				vACTRET = ECODE_MALLOCFAIL_TASKSTACK;
				goto __ACTEND;
			}
			#elif SYSCFG_TASKCREATEMODE == __DYNAMIC__
			node_news = NULL;
			node_news = (tspTaskNode)__malloc(sizeof(tsTaskNode));
			if(node_news != NULL)
			{
				node_news->stacksize = vACTBUF->stacksize;
				if(node_news->stacksize < __BASICSTACKSIZE__)
				{
					node_news->stacksize = __BASICSTACKSIZE__;
					#if SYSCFG_DEBUGGING == __ENABLED__
					node_news->realloc = true;
					#endif
				}
				#if SYSCFG_DEBUGGING == __ENABLED__
				else
				{
					node_news->realloc = false;
				}
				#endif
				node_news->BSP = NULL;
				node_news->BSP = (u8 *)__malloc(node_news->stacksize);
				if(node_news->BSP != NULL)
				{
					mTaskStack_INIT;
					node_news->TID = vACTBUF->TID;
					if(vACTBUF->TPL0 <= (u8)(SYSCFG_TASKPRIORITY - 1))
					{
						node_news->TPL = vACTBUF->TPL0;
					}
					else
					{
						node_news->TPL = SYSCFG_TASKPRIORITY - 2;
						#if SYSCFG_DEBUGGING == __ENABLED__
						vAlarm.overflow_taskpriority = true;
						#endif
					}
					node_news->state = (u8)vACTBUF->task_node;
					node_news->blocktype = 0;
					node_news->ptr = NULL;
					#if SYSCFG_DEBUGGING == __ENABLED__
					node_news->NAME = vACTBUF->NAME;
					node_news->usedtime[0] = 0;
					node_news->usedtime[1] = 0;
					node_news->stacklen_max = __BASICSTACKSIZE__;
					#endif
					node_news->saferuntime = vACTBUF->saferuntime;
					node_news->counter = 0;
					node_news->THDL = vACTBUF;
					vACTBUF->task_node = node_news;
					vDELAY_STMR[node_news->TID] = 0;
				}
				else
				{
					__free(node_news);
					#if SYSCFG_DEBUGGING == __ENABLED__
					vFault.fail_startuptask = true;
					vFault.mallocfail_taskstack = true;
					#endif
					vACTRET = ECODE_MALLOCFAIL_TASKSTACK;
					goto __ACTEND;
				}
			}
			else
			{
				#if SYSCFG_DEBUGGING == __ENABLED__
				vFault.fail_startuptask = true;
				vFault.mallocfail_tasknode = true;
				#endif
				vACTRET = ECODE_MALLOCFAIL_TASKNODE;
				goto __ACTEND;
			}
			#endif
			if(!task_queue_len)
			{
				init_taskqueue;
			}
			else
			{
				init_node_midd;
				if(node_curr != node_tail && node_news->TPL <= node_curr->TPL)
				{
					do{
						move_backward;
					}while(node_curr != node_tail && node_news->TPL <= node_curr->TPL);
				}
				else if(node_curr != node_head && node_news->TPL > node_curr->TPL)
				{
					do{
						move_forward;
					}while(node_curr != node_head && node_news->TPL > node_curr->TPL);
				}
				if(node_news->TPL > node_curr->TPL)
				{
					insert_forward;
				}
				else if(node_curr == node_tail && node_curr->TPL == 0)
				{
					insert_forward;
				}
				else
				{
					insert_backward;
				}
			}
			task_queue_len++;
			vACTRET = ECODE_NOERR;
		}
		else
		{
			#if SYSCFG_DEBUGGING == __ENABLED__
			vFault.fail_startuptask = true;
			vAlarm.overflow_taskqueue = true;
			#endif
			vACTRET = ECODE_OVERFLOW_TASKQUEUE;
		}
		__ACTEND:
		vACTBUF = (tspTaskHandle)0;
		if(vRET_f)
		{
			return;
		}
		else
		{
			vTASKING->blocktype = vACTRET;
		}
	}
	/**
	 * @brief    任务优先级
	 * @detail   如果任务优先级发生改变，在执行服务时已经从任务队列中移除该节点，并加入到临时链表。
	 *           在此，从临时链表中依次取出各任务节点，并根据任务优先级大小重新加入到任务队列。
	 */
	if(vTPLTAIL != NULL)
	{
		node_temp = vTPLTAIL;
		do
		{
			node_news = node_temp;
			node_temp = node_temp->last;
			init_node_midd;
			if(node_curr != node_tail && node_news->TPL <= node_curr->TPL)
			{
				do{
					move_backward;
				}while(node_curr != node_tail && node_news->TPL <= node_curr->TPL);
			}
			else if(node_curr != node_head && node_news->TPL > node_curr->TPL)
			{
				do{
					move_forward;
				}while(node_curr != node_head && node_news->TPL > node_curr->TPL);
			}
			if(node_news->TPL > node_curr->TPL)
			{
				insert_forward;
			}
			else if(node_curr == node_tail && node_curr->TPL == 0)
			{
				insert_forward;
			}
			else
			{
				insert_backward;
			}
		}while(node_temp != NULL);
		vTPLTAIL = NULL;
	}
	/**
	 * @brief    查找就绪
	 * @detail   更新任务状态，并同步查找可以运行的、优先级最高的任务。
	 */
	init_node_head;
	while(true)
	{
		switch(node_curr->state)
		{
			case __BLOCKED__: // 阻塞状态
			{
				if(node_curr->blocktype == __DELAY__) // 延时阻塞状态
				{
					if(!vDELAY_STMR[node_curr->TID])
					{
						node_curr->state = __READY__;
						task_state_over;
					}
				}
				else // 非延时（超时）阻塞状态
				{
					if(!vDELAY_STMR[node_curr->TID]) // 已超时
					{
						node_curr->state = __FLOATING__;
						task_state_over;
						break;
					}
					switch(node_curr->blocktype & 0x0F) // 未超时 || 无限等待 -> 查询阻塞事件
					{
						case 1:
						{
							if(*(u8  *)node_curr->ptr)
							{
								node_curr->state = __FLOATING__;
								task_state_over;
							}
						}
						break;
						case 2:
						{
							if(*(u16 *)node_curr->ptr)
							{
								node_curr->state = __FLOATING__;
								task_state_over;
							}
						}
						break;
						case 4:
						{
							if(*(u32 *)node_curr->ptr)
							{
								node_curr->state = __FLOATING__;
								task_state_over;
							}
						}
						break;
						case 0x0F:
						{
							if(!*(u8 *)node_curr->ptr)
							{
								node_curr->state = __FLOATING__;
								task_state_over;
							}
						}
						break;
					}
				}
			}
			break;
			case __FLOATING__: // 浮动状态
			{
				if(!vDELAY_STMR[node_curr->TID]) // 已超时
				{
					task_state_over;
					break;
				}
				switch(node_curr->blocktype & 0x0F) // 未超时 || 无限等待 -> 查询阻塞事件
				{
					case 1:
					{
						if(*(u8  *)node_curr->ptr)
						{
							task_state_over;
						}
						else
						{
							node_curr->state = __BLOCKED__;
						}
					}
					break;
					case 2:
					{
						if(*(u16 *)node_curr->ptr)
						{
							task_state_over;
						}
						else
						{
							node_curr->state = __BLOCKED__;
						}
					}
					break;
					case 4:
					{
						if(*(u32 *)node_curr->ptr)
						{
							task_state_over;
						}
						else
						{
							node_curr->state = __BLOCKED__;
						}
					}
					break;
					case 0x0F:
					{
						if(!*(u8 *)node_curr->ptr)
						{
							task_state_over;
						}
						else
						{
							node_curr->state = __BLOCKED__;
						}
					}
					break;
				}
			}
			break;
			case __READY__: // 就绪状态
			{
				task_state_over;
			}
			break;
			case __DELETED__: // 删除状态
			{
				if(node_curr != vTASKING) // node_curr非当前任务应立即删除，否则应在当前任务后处理时删除
				{
					node_remove;
					#if SYSCFG_TASKCREATEMODE != __STATIC__
					__free(node_curr->BSP);
					#endif
					#if SYSCFG_TASKCREATEMODE == __DYNAMIC__
					((tspTaskHandle)node_curr->THDL)->task_node = NULL;
					__free(node_curr);
					#endif
				}
			}
			break;
			#if SYSCFG_SAFERUNTIME == __ENABLED__
			case __OVERTIME__: // 超时状态
			{
				if(!vOVERTIME[node_curr->TID]) 
				{
					node_curr->state = __READY__;
					task_state_over;
				}
			}
			break;
			#endif
		}
		move_backward;
		/* 当前任务优先级组查询完毕 -> 当前任务预处理 */
		if(rotate_f && node_curr->TPL != vTASKING->TPL)
		{
			goto __TASKING_PREPROCESS;
		}
	}
	
	/* 准备任务调度：首次任务调度 -> 新任务预处理 */
	__TASK_SCHEDULING:
	if(vTASKING == NULL)
	{
		goto __NEWTASK_PREPROCESS;
	}
	
	/* 当前任务预处理 */
	__TASKING_PREPROCESS:
	{
		/* 当前任务栈长 */
		mTaskStack_LEN;
		/* 当前任务最大栈长 */
		#if SYSCFG_DEBUGGING == __ENABLED__
		if(stacklen > vTASKING->stacklen_max)
		{
			vTASKING->stacklen_max = stacklen;
		}
		#endif
		/* 每调度监控 */
		mEvery_Monitor;
	}
	
	/* 开始任务调度 */
	{
		/* 新任务与当前任务优先级不同 -> 当前任务后处理 */
		if(node_news->TPL != vTASKING->TPL)
		{
			goto __TASKING_POSTPROCESS;
		}
		/* 当前任务可以运行 && 时间片未到期 -> 返回 */
		if(vTickCounter < OS_TIMESHARING && vTASKING->state <= __FLOATING__)
		{
			vTASKING->state = __READY__;
			return;
		}
		/* 当前任务不可运行 || 时间片已到期 -> 时间片轮转调度 */
		node_curr = vTASKING;
		move_backward;
		while(node_last != node_tail && node_last->TPL == node_curr->TPL)
		{
			if(node_curr->state > __FLOATING__)
			{
				move_backward;
			}
			else
			{
				node_news = node_curr;
				goto __TASKING_POSTPROCESS;
			}
		}
		/* 新任务仍为当前任务，说明时间片已到期 -> 返回 */
		if(node_news == vTASKING)
		{
			vTASKING->state = __READY__;
			vTickCounter = 0;
			return;
		}
	}
	
	/* 当前任务后处理 */
	__TASKING_POSTPROCESS:
	{
		/* 当前任务状态为合法 -> 入栈监控 */
		if(vTASKING->state < __STOPPED__)
		{
			mPUSH_Monitor;
		}
		/* 当前任务状态为删除 -> 删除当前任务 */
		else if(vTASKING->state == __DELETED__)
		{
			node_curr = vTASKING;
			node_remove;
			#if SYSCFG_TASKCREATEMODE != __STATIC__
			__free(node_curr->BSP);
			#endif
			#if SYSCFG_TASKCREATEMODE == __DYNAMIC__
			((tspTaskHandle)node_curr->THDL)->task_node = NULL;
			__free(node_curr);
			#endif
		}
	}
	
	/* 新任务预处理 */
	__NEWTASK_PREPROCESS:
	{
		node_news->state = __READY__;
		vTickCounter = 0;
		#if SYSCFG_DEBUGGING == __ENABLED__
		if(vTaskmgrBinary)
		{
			counter = mSysTick_Counter;
		}
		#endif
	}
	
	/* 当前任务入栈 */
	if(push_f)
	{
		#if SYSCFG_DEBUGGING == __ENABLED__
		if(vTaskmgrBinary) mUsedTime_END;
		#endif
		mTaskStack_PUSH;
	}
	
	/* 新任务出栈 */
	{
		#if SYSCFG_DEBUGGING == __ENABLED__
		if(vTaskmgrBinary) mUsedTime_INIT;
		#endif
		mTaskStack_POP;
	}
}
}
